#include <iostream>
#include<unistd.h>
#include<cassert>
 #include <cstdlib>
 #include<cstdio>
 #include<cstring>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
    int fd[2];
    int ret = pipe(fd);
    std::cout<<"fd[0]："<<fd[0]<<std::endl;
    std::cout<<"fd[1]："<<fd[1]<<std::endl;
    int id = fork();
    assert(id>= 0);
    if(id == 0)
    {//子进程
        close(fd[0]);
        const char* str = "我是子进程，我正在给你发消息！";
        int ct =1;
        while(true)
        {
            char buf[1024]; 
            snprintf(buf, sizeof buf,"child---->parent say: %s[%d],我的PID是：%d",str,ct++,getpid());
            write(fd[1], buf, strlen(buf));
            sleep(1);
            std::cout<<ct<<std::endl;
        }

        close(fd[1]);//子进程关闭写端文件描述符号。
        std::cout<<"子进程关闭写端文件描述符号"<<std::endl;
        exit(0);
    }

    //父进程
    close(fd[1]);
    while(true)
    {
        char buf[1024];
        ssize_t s = read(fd[0], buf, sizeof(buf) - 1);
        if(s > 0 )//读取成功了
        {
            buf[s] = 0;
            std::cout<<"我是父进程我收到一条消息："<<"#############"<<buf<<std::endl;
        }
        else if ( s == 0)//子进程读到文件结尾。
        {
            std::cout<< "read：" << s << std::endl;
            break;//父进程不读了
        }
        break;
    }
    close(fd[0]);//关闭读取端文件描述符。
    std::cout<<"关闭读取端文件描述符号"<<std::endl;

    int status = 0;
    ret = waitpid(id,&status, 0);
    assert(ret == id);
    std::cout<<"子进程等待成功"<<std::endl;
    if((status&0x7F) == 0)
    {
        std::cout<<"子进程正常退出"<<std::endl;
        std::cout<<"子进程的退出码是："<<((status>>8)&0xFF)<< std::endl;
    }
    else
    {
        std::cout<<"子进程异常退出"<<std::endl;
        std::cout<<"子进程退出信号是："<< (status&0x7F) << std::endl;
    }

    return 0;
}



// int main()
// {
//     int fd[2];
//     int ret = pipe(fd);
//     //创建了一个匿名管道文件，并且被把读取端和写入端的文件描述符存入fd数组中。
//     //fd[0]:读取端
//     //fd[1]:写入端
//     std::cout<<"fd[0]："<<fd[0]<<std::endl;//3，这个是读取端
//     std::cout<<"fd[1]："<<fd[1]<<std::endl;//4，这个是写入端
//     int id = fork();
//     assert(id>= 0);
//     if(id == 0)
//     {//子进程
//         //我们让子进程给父进程发送信息
//         //子进程写入，父进程读取。
//         //子进程 --->  父进程
//         //我们关系子进程的读取端
//         close(fd[0]);
//         //开始发送信息
//         const char* str = "我是子进程，我正在给你发消息！";
//         int ct =1;
//         while(true)
//         {
//             char buf[1024];
//             snprintf(buf, sizeof buf,"child---->parent say: %s[%d],我的PID是：%d",str,ct++,getpid());
//             write(fd[1], buf, strlen(buf));//这里strlen不需要加1
//             //主要不能直接使用 ，文件描述符常数，不能使用 3，4等等。
//             sleep(1);
//         }
//         //严谨一点,用完之后把写入端也关闭。
//         close(fd[1]);
//         exit(0);
//     }

//     //父进程
//     //子进程 --->  父进程
//     close(fd[1]);//关闭父进程的写入端，保留读取
//     //开始读取信息。
//     while(true)
//     {
//         char buf[1024];
//         ssize_t s = read(fd[0], buf, sizeof(buf) - 1);//我们希望当成字符串处理，所以sizeof需要 -1 最后一位放置 '\0'
//         //
//         if(s > 0 )//读取成功了
//         {
//             buf[s] = 0;
//         }
//         std::cout<<"我是父进程我收到一条消息："<<"#############"<<buf<<std::endl;
//     }


//     ret = waitpid(id,0, 0);//阻塞等待
//     assert(ret == id);
//     //严谨一点,用完之后把写读取也关闭。
//     close(fd[0]);

//     return 0;
// }
